数码管日历表

用到8253 8259 8279,七段数码管。键盘,显示屏等外设
;连线说明
;E5区 :CLK(8279) ———— B2区:2M
;E5区 :CS(8279)、A0 ———— A3区:CS5、A0
;E5区 :A、B、C、D(8279) ———— G5区:A、B、C、D
;B3区 :CS(8259)、A0 ———— A3区:CS1、A0
;B3区:INT、INTA ———— ES8688:INTR、INTA
;B3区:IR0 ———— C5区 :OUT0
;C5区 :CS(8253)、A0、A1———— A3区:CS2、A0、A1
;C5区 :GATE0 ———— C1区:VCC
;C5区 :CLK0 ———— B2区:62.5K
;A1区:CS、RW、RS、CS1/2 A3区:CS4、A0、A1、A2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
.MODEL TINY
EXTRN Display8:NEAR, GetKeyA:NEAR
IO8259_0 EQU 0F000H
IO8259_1 EQU 0F001H
Con_8253 EQU 0E003H
T0_8253 EQU 0E000H
DATA_8279 EQU 0BF00H ;8279读写数据口的地址
;==========液晶屏LCD========
WR_COM_AD_L EQU 0C004H ;写左半屏指令地址 ;片选CS4
WR_COM_AD_R EQU 0C000H ;写右半屏指令地址
WR_DATA_AD_L EQU 0C006H ;写左半屏数据地址
WR_DATA_AD_R EQU 0C002H ;写右半屏数据地址
RD_BUSY_AD EQU 0C001H ;查忙地址
RD_DATA_AD EQU 0C003H ;读数据地址
X EQU 0B8H ;起始显示行基址
Y EQU 040H ;起始显示列基址
FirstLine EQU 0C0H
;====================
.STACK 200
.DATA
halfsec DB 0 ;0.5秒计数
sec DB 0 ;秒
min DB 0 ;分
hour DB 0 ;时
day DB 0 ;日
month DB 0 ;月
year DW 0 ;年
yearLowPos2 DB 0 ;年的低两位
yearHighPos2 DB 0 ;年的高两位
bufferTime DB 8 DUP(0) ;显示时间缓冲区,8个字节
bufferTimeSetting DB 8 DUP(0) ;显示设置时间缓冲区,8个字节
bufferDate DB 8 DUP(0) ;显示日期缓冲区,8个字节
bufferDateSetting DB 8 DUP(0) ;显示设置日期缓冲区,8个字节
timeNeedFlashDisp DB 0 ;时间需要刷新显示
dateNeedFlashDisp DB 0 ;日期需要刷新显示
displayTimeFlag DB 0 ;显示日期还是显示时间(显示时间为1,显示日期为0)
TimePos DB 0 ;时间位标志,设置哪一位时间
DatePos DB 0 ;日期位标志,设置哪一位日期
timeSettingFlash DB 0 ;时间设置时是否需要刷新
dateSettingFlash DB 0 ;日期设置时是否需要刷新
LeapYear DB 0 ;闰年标志
MonthHas30Day DB 0 ;天数为30天的月份标志
;========液晶屏LCD================
ZERO DB 000H,0E0H,010H,008H,008H,010H,0E0H,000H,000H,00FH,010H,020H,020H,010H,00FH,000H
DB 000H,010H,010H,0F8H,000H,000H,000H,000H,000H,020H,020H,03FH,020H,020H,000H,000H
DB 000H,070H,008H,008H,008H,088H,070H,000H,000H,030H,028H,024H,022H,021H,030H,000H
DB 000H,030H,008H,088H,088H,048H,030H,000H,000H,018H,020H,020H,020H,011H,00EH,000H
DB 000H,000H,0C0H,020H,010H,0F8H,000H,000H,000H,007H,004H,024H,024H,03FH,024H,000H
DB 000H,0F8H,008H,088H,088H,008H,008H,000H,000H,019H,021H,020H,020H,011H,00EH,000H
DB 000H,0E0H,010H,088H,088H,018H,000H,000H,000H,00FH,011H,020H,020H,011H,00EH,000H
DB 000H,038H,008H,008H,0C8H,038H,008H,000H,000H,000H,000H,03FH,000H,000H,000H,000H
DB 000H,070H,088H,008H,008H,088H,070H,000H,000H,01CH,022H,021H,021H,022H,01CH,000H
DB 000H,0E0H,010H,008H,008H,010H,0E0H,000H,000H,000H,031H,022H,022H,011H,00FH,000H
POINT DB 000H,000H,000H,0C0H,0C0H,000H,000H,000H,000H,000H,000H,030H,030H,000H,000H,000H
;=============================
.CODE
;========================主程序========================
START: MOV AX,@DATA
MOV DS,AX
MOV ES,AX
NOP
MOV sec,58 ;时分秒赋初值23:59:58
MOV min,59
MOV hour,23
MOV day,30 ;年月日赋初值2017 03 30
MOV month,3
MOV yearHighPos2,20
MOV yearLowPos2,17
MOV timeNeedFlashDisp,1 ;显示初始时间 置为1
MOV dateNeedFlashDisp,0
MOV displayTimeFlag,1 ;初始显示标志为时间 置为1
CALL Init8253 ;调用8253初始化程序
CALL Init8259 ;调用8259初始化程序
CALL WriIntver ;写中断向量表
CALL LCDCLEAR ;清LCD屏
CALL LCD_INIT ;初始化LCD
STI
Main: CALL GetKeyA ;扫描按键
JNB Key_Null ;没有按键,跳转至NoKey
CMP AL,0EH ;按键是否>=E
JB Key_Blow_E ;按键<E 则跳至Key_Blow_E
Key_is_E_F: CMP AL,0FH ;判断按键为E还是F
JNZ Main ;按键不为F 则按键为E,取消设置,回到主程序Main
CMP displayTimeFlag,1 ;按键为F,判断正在显示时间还是日期
JNZ DateSet ;若displayTimeFlag!=1 说明是正在显示日期 所以跳转至DataSet
TimeSet: CALL SetTime ;若时间显示标志位displayTimeFlag=1,说明正在显示时间,则调用SetTime设置时间子程序
TimeDisplay:CALL Display_LED_Time ;然后调用显示时间
MOV timeNeedFlashDisp,0
JMP Main
DateNeedDisp:CMP dateNeedFlashDisp,1
JNZ Main
CALL Display_LED_Date
MOV dateNeedFlashDisp,0
JMP Main
DateSet: CALL SetDate
;JMP DateDisplay ;设置完日期后,需要显示新的日期,跳转至DateDisplay
DateDisplay:CALL Display_LED_Date
MOV dateNeedFlashDisp,0
JMP Main ;显示完日期后,回到主程序Main
Key_Blow_E: CMP AL,0DH ;按键为D
JNZ Key_Null
NOT displayTimeFlag ;将displayTimeFlag取反
Key_Null: CMP displayTimeFlag,1
JNZ DateNeedDisp
CMP timeNeedFlashDisp,1
JNZ Main
JMP TimeDisplay
;=================================================
;================时间设定子程序==================
SetTime PROC NEAR
LEA SI,bufferTimeSetting ;之前时间信息放到设置缓存里,以便显示
CALL TimeToBuffer
MOV TimePos,0 ;将时间位标志置0,设置时间的第0位,时的十位数
Key: CMP timeSettingFlash,1 ;判断是否需要闪烁当前位
JNZ GetKey ;扫描键盘
LEA SI,bufferTimeSetting
LEA DI,bufferTime
MOV CX,8 ;重复8次
REP MOVSB
CMP halfsec,0
JNZ Flash
MOV BL,TimePos
NOT BL
AND BX,07H
LEA SI,bufferTime
MOV BYTE PTR [SI+BX],10H ;当前设置位置产生闪烁效果
Flash:LEA SI,bufferTime
CALL Display8
MOV timeSettingFlash,0
GetKey:CALL GetKeyA
JNB Key
CMP AL,0EH ;放弃设置
JNZ EarlyConfirm
JMP SetTimeExit
EarlyConfirm:CMP AL,0FH ;判断设置时间时是否按下F键,若按下F键,提前确认设置
JZ SettedTimeToVariable
SetTime_hour_High:CMP AL,10 ;数值范围为0~9
JNB Key ;无效按键
CMP TimePos,0
JNZ SetTime_hour_Low
CMP AL,3 ;调整时的十位数(范围为0~2)
JNB Key
MOV bufferTimeSetting + 7,AL
JMP SetTimeIsFinished
SetTime_hour_Low:CMP TimePos,1 ;时的个位
JNZ SetTime_min_High
CMP bufferTimeSetting + 7,2 ;判断时的十位是否为2,然后,调整时的个位(当时的十位为0和1时,
JB SetTime_hour_Low_1 ;其个位范围为0~9,当时为2时,个位范围为0~3)
CMP AL,4 ;当时的十位为2,判断个位是否小于4(0~3)
JNB Key ;若大于3则跳至Key,无效按键
SetTime_hour_Low_1:MOV bufferTimeSetting + 6,AL ;时的个位数
INC TimePos ;TimePos=2,这是个横杠“-”,跳过不用设置这位
JMP SetTimeIsFinished
SetTime_min_High:CMP TimePos,3 ;分的十位数
JNZ SetTime_min_Low
CMP AL,6 ;调整分的十位数(范围为0~5)
JNB Key ;若大于5则跳至Key,无效按键
MOV bufferTimeSetting + 4,AL
JMP SetTimeIsFinished
SetTime_min_Low:CMP TimePos,4 ;分的个位数
JNZ SetTime_sec_High
MOV bufferTimeSetting + 3,AL ;调整分的个位数(范围为0~9)
INC TimePos ;TimePos=5,这是个横杠“-”,跳过不用设置这位
JMP SetTimeIsFinished
SetTime_sec_High:CMP TimePos,6 ;秒的十位数
JNZ SetTime_sec_Low
CMP AL,6 ;调整秒的十位数(范围为0~5)
JB SetTime4_sec_High_1
JMP Key ;若大于5则跳至Key,无效按键
SetTime4_sec_High_1:MOV bufferTimeSetting + 1,AL
JMP SetTimeIsFinished
SetTime_sec_Low:MOV bufferTimeSetting,AL ;调整秒的个位数(范围为0~9)
SetTimeIsFinished:INC TimePos
CMP TimePos,8 ;判断是否设置完(是否时间位标志=8),设置完跳转SettedTimeToVariable同步信息
JNB SettedTimeToVariable
MOV timeSettingFlash,1 ;需要刷新
JMP Key
SettedTimeToVariable:MOV AL,bufferTimeSetting + 1 ;设置的时间转换到变量中;同步信息
MOV BL,10
MUL BL
ADD AL,bufferTimeSetting
MOV sec,AL ;秒
MOV AL,bufferTimeSetting + 4
MUL BL
ADD AL,bufferTimeSetting + 3
MOV min,AL ;分
MOV AL,bufferTimeSetting + 7
MUL BL
ADD AL,bufferTimeSetting + 6
MOV hour,AL ;时
CMP hour,24 ;以下程序是实现避免非法显示功能的,将当前小时数和24比较,若hour<24则跳至SetTimeExit,否则将hour-=24
JB SetTimeExit
SUB hour,24 ;当前小时数hour大于了24,将hour-=24
SetTimeExit: RET
SetTime ENDP
;========================日期设定========================
SetDate PROC NEAR
LEA SI,bufferDateSetting
CALL DateToBuffer
MOV DatePos,0
Key_Date:CMP dateSettingFlash,1 ;判断是否需要闪烁当前位
JNZ Date_GetKey
LEA SI,bufferDateSetting ;将bufferDateSetting中的数据存SI中
LEA DI,bufferDate
MOV CX,8
REP MOVSB ;将bufferDateSetting中的数据拷贝到bufferDate中
CMP halfsec,0
JNZ FLASH1
MOV BL,DatePos
NOT BL ;BL = 1111H
AND BX,07H ;BX = 07H
LEA SI,bufferDate ;将bufferDate的偏移地址存入SI中
MOV BYTE PTR [SI+BX],10H ;当前设置位置产生闪烁效果
FLASH1:LEA SI,bufferDate
CALL DisPlay8 ;显示日期
MOV dateSettingFlash,0
Date_GetKey:CALL GetKeyA ;扫描键盘
JNB Key_Date ;若无按键则跳转
CMP AL,0EH ;放弃设置
JNZ KeyIsF ;若按的不是E则跳至KeyIsF,判断是否按下F键
JMP SetDateExit ;按E放弃设置,退出返回
KeyIsF:CMP AL,0FH ;判断设置时间时是否按下F键,若按下F键,提前确认设置
JNZ DateKeyNotF ;按键不为F则继续设定
JMP DateBufferToVariable ;按键为F则确定
DateKeyNotF:CMP AL,10 ;日期按键在10以内
JNB Key_Date ;大于等于10的按键则为无效按键
CMP DatePos,0 ;是否为第一位
JNZ SetDate_y_1
MOV bufferDateSetting + 7,AL ;调整年的千位数
JMP SetDateIsFinished
SetDate_y_1: CMP DatePos,1 ;是否为第二位
JNZ SetDate_y_2
MOV bufferDateSetting + 6,AL ;调整年的百位数
JMP SetDateIsFinished
SetDate_y_2: CMP DatePos,2
JNZ SetDate_y_3
MOV bufferDateSetting + 5,AL ;调整年的十位数
JMP SetDateIsFinished
SetDate_y_3: CMP DatePos,3
JNZ JudgeLeap
MOV bufferDateSetting + 4,AL ;调整年的个位数
JMP SetDateIsFinished
JudgeLeap:CALL JudgeLeapYear ;判断是否为闰年
CMP DatePos,4
JNZ SetDate4_1
CMP AL,2
JB SetDate_m_0
JMP Key_Date ;无效按键(月的十位大于了1)
SetDate_m_0:MOV bufferDateSetting + 3,AL ;调整月的十位数
JMP SetDateIsFinished
SetDate4_1:CMP DatePos,5
JNZ SetDate5
CMP bufferDateSetting + 3,0 ;调整月的个位数
JZ SetDate4_2 ;月的十位是0则跳转
CMP AL,3
JB SetDate_m_1
JMP Key_Date ;无效按键
SetDate4_2: CMP AL,0
JA SetDate_m_1
JMP Key_Date
SetDate_m_1:MOV bufferDateSetting + 2,AL ;月的个位数
JMP SetDateIsFinished
SetDate5: CALL JudgeMonthIs30day ;判断是否为天数为30天的月份
PUSH AX
MOV AL,bufferDateSetting + 3
MOV BL,10
MUL BL
ADD AL,bufferDateSetting + 2 ;将当前月份记入AL中
MOV month,AL ;将AL存入month中
POP AX
CMP DatePos,6
JNZ SetDate6
CMP month,2 ;是否为2月
JNZ SetDate5_0 ;不是2月则跳转
CMP AL,3
JB SetDate5_2
JMP Key_Date
SetDate5_2: JMP SetDate_d_0
SetDate5_0: CMP AL,4 ;调整日的十位数 (判断日十位数是否<=3)
JB SetDate_d_0
JMP Key_Date ;无效按键
SetDate_d_0:MOV bufferDateSetting + 1,AL
JMP SetDateIsFinished
SetDate6: CMP DatePos,7
JNZ DateBufferToVariable
CMP month,2 ;判断是否为2月
JNZ SetDate6_0 ;不是2月则跳转
CMP LeapYear,0 ;是2月,判断是否为闰年
JZ SetDate6_2 ;不是闰跳转
JMP SetDate_d_1 ;是闰年
SetDate6_2: CMP AL,9 ;当前是2月份以及不是闰年的情况下,判断日的个位数是否小于9
JB SetDate_d_1
JMP Key_Date
SetDate6_0: CMP bufferDateSetting + 1 ,3 ;判断日的十位是否为3
JNZ SetDate_d_1 ;不是3跳转
CMP MonthHas30Day,0 ;是3,判断是否为小月
JZ SetDate6_3 ;不是小月则跳转
CMP AL,1
JB SetDate_d_1
JMP Key_Date
SetDate6_3: CMP AL,2
JB SetDate_d_1
JMP Key_Date
SetDate_d_1: MOV bufferDateSetting,AL ;调整日的个位数
SetDateIsFinished: INC DatePos
CMP DatePos,8
JNB DateBufferToVariable ;大于等于第8位则确定
MOV dateSettingFlash,1 ;8位没设定完则继续,日期需要刷新
JMP Key_Date
DateBufferToVariable:MOV AL,bufferDateSetting + 1 ;确认
MOV BL,10
MUL BL
ADD AL,bufferDateSetting
MOV day,AL ;日
MOV AL,bufferDateSetting + 3
MUL BL
ADD AL,bufferDateSetting + 2
MOV month,AL ;月
MOV AL,bufferDateSetting + 5
MUL BL
ADD AL,bufferDateSetting + 4
MOV yearLowPos2,AL
MOV AL,bufferDateSetting + 7
MUL BL
ADD AL,bufferDateSetting + 6
MOV yearHighPos2,AL
CALL JudgeLeapYear
CMP month,13
JB SetDate8_0 ;以下程序是实现避免非法显示功能的
SUB month,12 ;月数大于12则month-=12
SetDate8_0: CMP month,2
JNZ SetDate8_1
CMP LeapYear,1
JZ SetDate8_3
CMP day,28
JNA SetDateExit
SUB day,28
JMP SetDateExit
SetDate8_1: CALL JudgeMonthIs30day
CMP MonthHas30Day,1
JNZ SetDate8_2
CMP day,30
JNA SetDateExit
SUB day,30
JMP SetDateExit
SetDate8_2: CMP day,31
JNA SetDateExit
SUB day,31
JMP SetDateExit
SetDate8_3: CMP day,29
JNA SetDateExit
SUB day,29
JMP SetDateExit
SetDateExit: RET
SetDate ENDP
;========================是否为闰年========================
JudgeLeapYear PROC NEAR
PUSH AX
PUSH BX
PUSH DX
LEA SI,bufferDateSetting
MOV AL,bufferDateSetting + 7 ;年的千位数
XOR AH,AH
MOV BL,10
MUL BL ;年的千位数*10
ADD AL,bufferDateSetting + 6 ;年的千位数*10+年的百位数
MUL BL ;(年的千位数*10+年的百位数)*10
ADD AL,bufferDateSetting + 5 ;(年的千位数*10+年的百位数)*10+年的十位数
MUL BL ;[(年的千位数*10+年的百位数)*10+年的十位数]*10
ADD AL,bufferDateSetting + 4 ;[(年的千位数*10+年的百位数)*10+年的十位数]*10+年的各位位数
MOV year,AX
XOR DX,DX
MOV BX,400
DIV BX
CMP DX,0 ;能整除DX=0
JZ JudgeLeapYear2 ;能被400整除为闰年
MOV AX,year
XOR DX,DX
MOV BX,4
DIV BX
CMP DX,0
JZ JudgeLeapYear1 ;能被4整除则跳转
JMP JudgeLeapYear3
JudgeLeapYear1: MOV AX,year
XOR DX,DX
MOV BX,100
DIV BX
CMP DX,0
JZ JudgeLeapYear3 ;能被100整除则跳转
JudgeLeapYear2: MOV LeapYear,1 ;能被4整除不能被100整除为闰年
JMP PopT
JudgeLeapYear3: MOV LeapYear,0 ;不能被4整除不是闰年
;能被4整除且能被100整除的不是闰年
PopT: POP DX
POP BX
POP AX
RET
JudgeLeapYear ENDP
;====================是否为天数为30天的月份====================
;=======================4月6月9月11月=========================
JudgeMonthIs30day PROC NEAR
PUSH AX
PUSH BX
MOV AL,bufferDateSetting + 3
MOV BL,10
MUL BL
ADD AL,bufferDateSetting + 2
CMP AX,4
JZ Here
CMP AX,6
JZ Here
CMP AX,9
JZ Here
CMP AX,11
JZ Here
MOV MonthHas30Day,0
JMP Pop1
Here: MOV MonthHas30Day,1
Pop1: POP BX
POP AX
RET
JudgeMonthIs30day ENDP
;========================显示时分秒========================
Display_LED_Time PROC NEAR
LEA SI,bufferTime
CALL TimeToBuffer
LEA SI,bufferTime
CALL Display8 ;显示
RET
Display_LED_Time ENDP
;显示年月日
Display_LED_Date PROC NEAR
LEA SI,bufferDate
CALL DateToBuffer
LEA SI,bufferDate
;CALL Display8_1 ;显示
CALL DisPlay8
RET
Display_LED_Date ENDP
;==============hour min sec转化成可显示格式=================
TimeToBuffer PROC NEAR
MOV AL,sec
XOR AH,AH
MOV BL,10
DIV BL
MOV [SI],AH
MOV [SI + 1],AL ;秒
MOV BYTE PTR [SI + 2],10H ;不显示
MOV AL,min
XOR AH,AH
DIV BL
MOV [SI + 3],AH
MOV [SI + 4],AL ;分
MOV BYTE PTR [SI + 5],10H ;这位不显示
MOV AL,hour
XOR AH,AH
DIV BL
MOV [SI + 6],AH
MOV [SI + 7],AL ;时
RET
TimeToBuffer ENDP
;==============day month year转换为可显示格式==============
DateToBuffer PROC NEAR
MOV AL,day
XOR AH,AH
MOV BL,10
DIV BL
MOV [SI],AH ;余数为日的个位
MOV [SI + 1],AL ;商为日的十位
MOV AL,month
XOR AH,AH
DIV BL
MOV [SI + 2],AH ;余数为月的个位
MOV [SI + 3],AL ;商为月的十位
MOV AL,yearLowPos2
XOR AH,AH
DIV BL
MOV [SI + 4],AH ;余数为年的个位
MOV [SI + 5],AL ;商为年的十位
MOV AL,yearHighPos2
XOR AH,AH
DIV BL
MOV [SI + 6],AH ;余数为年的百位
MOV [SI + 7],AL ;商为年的千位
RET
DateToBuffer ENDP
;========================0.5s产生一次中断========================
CalendarInt PROC NEAR
PUSH AX
PUSH DX
MOV timeSettingFlash,1 ;时间是否需要刷新
MOV dateSettingFlash,1 ;日期是否需要刷新
INC halfsec
CMP halfsec,2
JZ CalendarInt7
JMP CalendarInt1
CalendarInt7: MOV timeNeedFlashDisp,1
MOV dateNeedFlashDisp,1
MOV halfsec,0
INC sec
CMP sec,60
JZ CalendarInt8 ;秒满60则跳转
JMP CalendarInt1
CalendarInt8: MOV sec,0 ;当秒为60时将秒置为0
INC min ;给分加1
CMP min,60
JZ CalendarInt9 ;分满60则跳转
JMP CalendarInt1
CalendarInt9: MOV min,0 ;当分为60时将分置为0
INC hour ;给时加1
CMP hour,24
JNZ CalendarInt1
MOV hour,0 ;当时满24时将时置为0
INC day ;给天加1
CalendarInt2: CMP month,2 ;是否为2月
JNZ CalendarInt3 ;不是2月则跳转
CMP LeapYear,1 ;是否为闰年(0为否,1为是)
JNZ CalendarInt5 ;不是闰年则跳转
CMP day,30 ;是闰年
JNZ CalendarInt1
JMP CalendarInt6
CalendarInt5: CMP day,29
JNZ CalendarInt1
JMP CalendarInt6
CalendarInt3: CMP MonthHas30Day,0 ;是否为天数为30天的月份(0为否,1为是)
JNZ CalendarInt4 ;是小月则跳转
CMP day,32 ;不是小月
JNZ CalendarInt1
JMP CalendarInt6
CalendarInt4: CMP day,31
JNZ CalendarInt1
CalendarInt6: MOV day,1
INC month
CMP month,13
JNZ CalendarInt1
MOV month,1
INC yearLowPos2
CMP yearLowPos2,100
JNZ CalendarInt1
MOV yearLowPos2,0
INC yearHighPos2
CalendarInt1:
LEA SI,bufferTime
CALL DateToBuffer
CALL SHOWCALENDER ;在液晶显示器上显示年月日
LEA SI,bufferDate
CALL TimeToBuffer
CALL SHOWTIME ;在液晶显示器上显示时分秒
MOV DX,IO8259_0
MOV AL,20H
OUT DX,AL
POP DX
POP AX
IRET
CalendarInt ENDP
;========================8253初始化========================
Init8253 PROC NEAR
MOV DX,Con_8253 ;送控制寄存器端口地址给DX
MOV AL,34H ;00110100b 选择计数器0,先读写低字节,再读写高字节,方式2,二进制计数
OUT DX,AL ;计数器T0设置在模式2状态,HEX计数
MOV DX,T0_8253
MOV AL,12H ;设置计数初值
OUT DX,AL ;写计数值的低8位
MOV AL,7AH ;计数值的高8位
OUT DX,AL ;CLK0=62.5kHz,0.5s定时
RET
Init8253 ENDP
;========================8259初始化========================
Init8259 PROC NEAR
MOV DX,IO8259_0
MOV AL,13H ;中断类型号,设定边沿触发,单片方式
OUT DX,AL
MOV DX,IO8259_1
MOV AL,08H ;中断类型号,设定IRQ0的中断向量号位08H(中断源:电子钟时间基准)
OUT DX,AL
MOV AL,09H ;中断类型号,中断源:键盘
OUT DX,AL
MOV AL,0FEH
OUT DX,AL
RET
Init8259 ENDP
;========================设置中断向量========================
WriIntver PROC NEAR
PUSH ES
MOV AX,0
MOV ES,AX
MOV DI,20H
LEA AX,CalendarInt
STOSW
MOV AX,CS
STOSW
POP ES
RET
WriIntver ENDP
;==============数据写入8279数据端口==============
WRITE_DATA PROC NEAR
MOV DX,DATA_8279
OUT DX,AL
RET
WRITE_DATA ENDP
;------------------------------------以下是液晶显示屏相关-----------------------------------------
;液晶显示年月日的具体实现
SHOWCALENDER PROC NEAR
R0: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,24
call byteDISR
R1: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime+1
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,16
call byteDISR
R2: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime+2
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,8
call byteDISR
R3: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime+3
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,0
call byteDISR
R4: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime+4
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,56
call byteDISL
R5: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime+5
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,48
call byteDISL
R6: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime+6
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,40
call byteDISL
R7: LEA SI,ZERO
MOV AH,00
MOV AL, bufferTime+7
MOV BL,16
MUL BL
ADD SI,AX
mov al,2
mov ah,32
call byteDISL
RET
SHOWCALENDER ENDP
;液晶显示时分秒的具体实现
SHOWTIME PROC NEAR
A0: LEA SI,ZERO
MOV AH,00
MOV AL, bufferDate
MOV BL,16
MUL BL
ADD SI,AX
mov al,4
mov ah,24
call byteDISR
A1: LEA SI,ZERO
MOV AH,00
MOV AL, bufferDate+1
MOV BL,16
MUL BL
ADD SI,AX
mov al,4
mov ah,16
call byteDISR
AP: LEA SI,POINT
mov al,4
mov ah,8
call byteDISR
A2: LEA SI,ZERO
MOV AH,00
MOV AL, bufferDate+3
MOV BL,16
MUL BL
ADD SI,AX
mov al,4
mov ah,0
call byteDISR
A3: LEA SI,ZERO
MOV AH,00
MOV AL, bufferDate+4
MOV BL,16
MUL BL
ADD SI,AX
mov al,4
mov ah,56
call byteDISL
APOINT: LEA SI,POINT
mov al,4
mov ah,48
call byteDISL
A4: LEA SI,ZERO
MOV AH,00
MOV AL, bufferDate+6
MOV BL,16
MUL BL
ADD SI,AX
mov al,4
mov ah,40
call byteDISL
A5: LEA SI,ZERO
MOV AH,00
MOV AL, bufferDate+7
MOV BL,16
MUL BL
ADD SI,AX
mov al,4
mov ah,32
call byteDISL
RET
SHOWTIME ENDP
;延时程序
; DelayTime PROC NEAR
; MOV CX,0
; LOOP $
; LOOP $
; RET
; DelayTime ENDP
;液晶初始化
LCD_INIT PROC NEAR
MOV AL,3EH ;初始化左半屏,关显示
CALL WRComL ;写指令子程序
MOV AL,FirstLine ;设置起始显示行,第0行
CALL WRComL
MOV AL,3EH ;初始化右半屏,关显示
CALL WRComR ;写指令子程序
MOV AL,FirstLine ;设置起始显示行,第0行
CALL WRComR
;CALL LCDClear ;清屏
MOV AL,3FH ;开显示
CALL WRComL
MOV AL,3FH ;开显示
CALL WRComR
RET
LCD_INIT ENDP
;清屏
LCDClear PROC NEAR
;清左半屏
MOV AL,0 ;起始行,第0行
MOV AH,0 ;起始列,第0列
LCDClearL1: PUSH AX
MOV CX,64
CALL SETXYL ;设置起始显示行列地址
LCDClearL2: MOV AL,0
CALL WRDATAL
LOOP LCDClearL2
POP AX
INC AX
CMP AL,8 ;共8行
JNZ LCDClearL1
;清右半屏
MOV AL,0 ;起始行,第0行
MOV AH,0 ;起始列,第0列
LCDClearR1: PUSH AX
MOV CX,64
CALL SETXYR ;设置起始显示行列地址
LCDClearR2: XOR AL,AL
CALL WRDATAR
LOOP LCDClearR2
POP AX
INC AL
CMP AL,8 ;共8行
JNZ LCDClearR1
RET
LCDClear ENDP
;显示字体,显示一个数据要占用X行两行位置
;左半屏显示一个字节/字:AL-起始显示行序数X(0-7);AH-起始显示列序数Y(0-63);SI-显示字
数据首地址
ByteDisL PROC NEAR
MOV CX,8 ;显示8个字节数据,用于显示一个英文/符号
CALL DispL
RET
ByteDisL ENDP
WordDisL PROC NEAR
MOV CX,16 ;显示16字节数据,用于显示一个汉字
CALL DispL
RET
WordDisL ENDP
DispL PROC NEAR
PUSH AX
PUSH CX
CALL SETXYL ;设置起始显示行列地址
CALL DisplayL ;显示上半行数据
POP CX
POP AX
INC AL
CALL SETXYL ;设置起始显示行列地址
CALL DisplayL ;显示下半行数据
RET
DispL ENDP
;右半屏显示一个字节/字:AL-起始显示行序数X(0-7);AH-起始显示列序数Y(0-63);SI-显示字数据首地址
ByteDisR PROC ENAR
MOV CX,8 ;显示8个字节数据,用于显示一个英文/符号
CALL DispR
RET
ByteDisR ENDP
WordDisR PROC NEAR
MOV CX,16 ;显示16字节数据,用于显示一个汉字
CALL DispR
RET
WordDisR ENDP
DispR PROC NEAR
PUSH AX
PUSH CX
CALL SETXYR ;设置起始显示行列地址
CALL DisplayR ;显示上半行数据
POP CX
POP AX
INC AL
CALL SETXYR ;设置起始显示行列地址
CALL DisplayR ;显示下半行数据
RET
DispR ENDP
;显示图形
;显示左半屏一行图形,AL-X起始行序数(0-7),AH-Y起始列地址序数(0-63)
LineDisL PROC NEAR
MOV CX,64
CALL SETXYL ;设置起始显示行列
CALL DisplayL ;显示数据
RET
LineDisL ENDP
;显示右半屏一行图形,AL-X起始行地址序数(0-7),AH-Y起始列地址序数(0-63)
LineDisR PROC NEAR
MOV CX,64
CALL SETXYR ;设置起始显示行列
CALL DisplayR ;显示数据
RET
LineDisR ENDP
;基本控制
;显示左半屏数据,R7-显示数据个数
DisplayL PROC NEAR
LODSB
CALL WRDataL ;写左半屏数据
LOOP DisplayL
RET
DisplayL ENDP
;显示右半屏数据,R7-显示数据个数
DisplayR PROC NEAR
LODSB
CALL WRDataR ;写左半屏数据
LOOP DisplayR
RET
DisplayR ENDP
;设置左半屏起始显示行列地址,AL-X起始行序数(0-7),AH-Y起始列序数(0-63)
SETXYL PROC NEAR
OR AL,X ;行地址=行序数+行基址
CALL WRComL
MOV AL,AH
OR AL,Y ;列地址=列序数+列基址
CALL WRComL
RET
SETXYL ENDP
;设置右半屏起始显示行列地址,AL-X起始行序数(0-7),AH-Y起始列序数(0-63)
SETXYR PROC NEAR
OR AL,X ;行地址=行序数+行基址
CALL WRComR
MOV AL,AH
OR AL,Y ;列地址=列序数+列基址
CALL WRComR
RET
SETXYR ENDP
;写左半屏控制指令,A-写入指令
WRComL PROC NEAR
MOV DX,WR_COM_AD_L
OUT DX,AL
WRComL1: MOV DX,RD_BUSY_AD
IN AL,DX
TEST AL,80H ;检查液晶显示是否处于忙状态
JNZ WRComL1
RET
WRComL ENDP
;写右半屏控制指令,A-写入指令
WRComR PROC NEAR
MOV DX,WR_COM_AD_R
OUT DX,AL
WRComR1: MOV DX,RD_BUSY_AD
IN AL,DX
TEST AL,80H ;检查液晶显示是否处于忙状态
JNZ WRComR1
RET
WRComR ENDP
;写左半屏数据,A-写入数据
WRDataL PROC NEAR
MOV DX,WR_DATA_AD_L
OUT DX,AL
WRDataL1: MOV DX,RD_BUSY_AD
IN AL,DX
TEST AL,80H ;检查液晶显示是否处于忙状态
JNZ WRDataL1
RET
WRDataL ENDP
;写右半屏数据,A-写入数据
WRDataR PROC NEAR
MOV DX,WR_DATA_AD_R
OUT DX,AL
WRDataR1: MOV DX,RD_BUSY_AD
IN AL,DX
TEST AL,80H ;检查液晶显示是否处于忙状态
JNZ WRDataR1
RET
WRDataR ENDP
END START

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器